// Progetto: Briscola
// compile with:
// g++ -export-dynamic Briscola.cc `pkg-config --cflags --libs gtk+-3.0`

/**@mainpage 
* Questo programma permette ad un utente di giocare una partita di briscola   
* contro il computer.

* Si è cercato di replicare in modo più simile possibile il gioco di carte 
* originale.  
*
* Se avrai una buona memoria per ricordarti le carte scese, e un po' di fortuna,
* allora la vittoria sarà tua!
* 
* Il gioco è strutturato su 5 file: Briscola_main.cc, inizial_gioco.cc, 
* manip_mano.cc, manip_turno.cc e turno_pc.cc
*
* Per lanciare il programma da terminare digitare il comando:
*
* ./Briscola
*
*  @author Sapienza Davide
*/

#include <iostream>
#include <gtk/gtk.h>
#include <cmath>
#include <ctime>
#include <stdlib.h>
#include <fstream>
#include <cstring>

#include "struttura_dati.h"
#include "manip_mano.h"
#include "manip_turno.h"
#include "inizial_gioco.h"
#include "turno_pc.h"

using namespace std;

partita_t partita;

/** Creazione dell'oggetto builder che permette di interagire con la GUI
 */
GtkBuilder *builder;

/** Creazione di un oggetto di tipo gioca_t. 
 *  Settato per default a giocatore, che inizierà sempre la partita
 */
gioca_t gioca = giocatore;

/** Creazione di un oggetto di tipo turno_t.
 *  Oggetto che serve per tenere il turno nella coppia di giocate dei due 
 *  sfidanti nella stessa mano.
 */
turno_t turno = primo;

/** Link alla documentazione di doxigen.
 *  Permette di aprire una pagina di firefox con la relativa documentazione in 
 *  formato html.
 */
extern "C" void carica_documentazione(GtkMenuItem *item, gpointer data){
	D1(cout<<"INIZIO DEBUG carica_documentazione"<<endl);
	system("firefox ../doc/html/index.html");
	D1(cout<<"FINE DEBUG DOCUMENTAZIONE :aperta con succeso"<<endl);
}
 
/** Inizializza la partita. 
 *  Funzione privata perchè usata solo all'interno di Briscola.cc,
 *  inizializza il mazzo e le mani con i rispettivi valori.
 */
static void inizializza_partita(){
	D1(cout<<"INIZIO DEBUG inizializza_partita"<<endl);
	// setta l'indice del mazzo a zero
  	partita.idx = 0;
	partita.id_fine=0;
	// inizializza a 0 tutto il mazzo
  	for(int i=0; i<40; i++){
		partita.mazzo[i].val=0;
		partita.mazzo[i].selez=false;
		// setta a true il campo esiste perchè considera che dopo il mazzo
 		// venga creato veramente
		partita.mazzo[i].esiste=true;						
		}
	D2(cout<<"inizializzato a zero la partita con successo"<<cout);
	// setta a 0 le mani del giocatore e del computer
	for(int i=0; i<NUM_MANO; i++){
		partita.player1.mano[i].val=0;
		partita.player2.mano[i].val=0;
		}
	D2(cout<<"inizializzato a zero i val delle mani dei due giocatori"<<endl);
	// setta a zero i punteggi dei 2 giocatori (giocatore e pc)
	partita.player1.punteggio=0;
	partita.player2.punteggio=0;
	
	//genera il mazzo
	genera_mazzo();
	D2(cout<<"mazzo generato con successo"<<endl);
	/* Quasto for è indispensabile per la prima volta, perchè carica_mano 
	 * è una funzione singola, perchè viene usata sia per caricare la mano,
 	 * che per l'aggiornare la mano.
	 * Setta come già selezionate le carte che i giocatori dovrebbero avere
	 * in mano, così carica mano può funzionare anche in questo caso, 
	 * ovvero, deve far pescare ad ogni giocatore le prime tre carte.
	 * In più setta che esistono le tre carte della mano.	
    */
	for(int i=0; i<3; i++){
		partita.player2.mano[i].selez = true;
		partita.player1.mano[i].selez = true;
		partita.player1.mano[i].esiste=true;						
		partita.player2.mano[i].esiste=true;
		}
	D2(cout<<"inizializzato i campi 'selez' e 'esiste' delle mani "<<endl);	
	// carica la mano di gioco con le carte
	carica_mano();
	D2(cout<<"caricato la mano con successo"<<endl);
	/* IMPORTANTE
	 * Fa idx++ perchè in questo momento punta alla carta del mazzo che però è
	 * la mia briscola, quindi non posso pescarla, e la salto perchè deve
    * rimanere fissa.
    */
	partita.idx++;
	
	/* Adesso setta le carte che si possono premere.
  	 * In questo caso saranno sempre le carte del giocatore, 
	 * perchè abbiamo detto che inizia sempre lui per primo.
	 */
	setta_mano();
	D2(cout<<"settato la mano con successo"<<endl);
	D1(cout<<"FINE DEBUG INIZIALIZZA"<<endl);
}

/** Segnale che chiude la rispettiva dialog aperta, prendendo il text
 *  della label agganciata al data.
 */
extern "C" void chiudi_dialog(GtkButton *button, gpointer data){
	D1(cout<<"INIZIO DEBUG chiudi_dialog"<<endl);
	// Prende il nome della label, che per me rappresenta il nome della dialog
	const char *nome_dia = gtk_label_get_text(GTK_LABEL(data));
	D2(cout<<"recuperato il nome dalla label"<<endl);
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,
								nome_dia)), false);
	D1(cout<<"FINE DEBUG CHIUDI DIALOG"<<endl);
}

/** Segnale che azzera tutta la partita, e la rilancia.				
 *  fa scomparire label eventualmente presemti, e fa comparire 
 *  immagini e label eventualmente mancanti.							
 */
extern "C" void azzera_tutto(GtkButton *button, gpointer data){
	D1(cout<<"INIZIO DEBUG azzera_tutto"<<endl);
	pulisci_tavolo();
	D2(cout<<"pulito tavolo con successo"<<endl);
	turno=primo;
	
	gioca=giocatore;

	inizializza_partita();
	D2(cout<<"inizializzato la partita con successo"<<endl);
	// setta a visible l'immagine del mazzo
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"mazz"))
					, true);
	
	gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(builder,"f")),"fine turno");

	// setta la label di fine turno non a visible 
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"f")), false);

	// rimetto la label delle carte mancanti
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"indice"))
					, true);
		
	// aggiorna l'immagine della briscola 
	gtk_image_set_from_file(GTK_IMAGE(gtk_builder_get_object(builder,"image1"))
					,partita.mazzo[6].nome);

	// l'immagine la risetta visible
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"image1"))
					, true);

	// rimette il mazzo a non editabile
	gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder,"mazzo"))
					,false);

	// ripristina la label delle carte mancanti
	gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(builder, "indice")),"33");

	// riazzera la label dei punti
	gtk_label_set_label(GTK_LABEL(gtk_builder_get_object(builder,"label1")),"00"); 

	// setta le carti a visible
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"0")),true);
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"1")),true);
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"2")),true);
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"3")),true);
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"4")),true);
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,"5")),true);

	//chiude la finestra di dialogo
	chiudi_dialog(button, data);
	D2(cout<<"chiusa dialog con successo"<<endl);
	D1(cout<<"FINE DEBUG AZZERA TUTTO"<<endl);
}

/** Segnale che gestisce sia la nuova partita che l'uscita dal gioco.
 *  Fa quindi comparire la dialog1 o dialog2
 */
extern "C" void handler_new_finish_match(GtkMenuItem *menuitem, gpointer data){
	D1(cout<<"INIZIO DEBUG handler_new_finish_match"<<endl);
	const char *nome_dia = gtk_label_get_text(GTK_LABEL(data));
	
		
	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,
								nome_dia)), true);
	D1(cout<<"FINE DEBUG HANDLER NEW FINISH MATCH"<<endl);
}

/** Segnale che serve solo per la gestione della chiusura della window dalla x
 *  della finestra
 */
extern "C" void handler_x_button(GtkMenuItem *menuitem,  GdkEvent *event, gpointer
						user_data){
	D1(cout<<"INIZIO DEBUG handler_x_button"<<endl);
	handler_new_finish_match(menuitem, user_data);
	D1(cout<<"FINE DEBUG HANDLER X BUTTON"<<endl);
}

/** Segnale che chiude il programma.
  */
extern "C" gboolean handler_delete_event (GtkWidget *widget,GdkEvent *event, 
						gpointer user_data){
	gtk_main_quit();
	return true;
	}


/** Segnale che gestisce la carta premuta.  
  * Gestisce quale giocatore ha premuto la carta, e a quale turno.
  */
extern "C" void carta_button_clicked(GtkButton *button, gpointer data){
	D1(cout<<"INIZIO DEBUG carta_button_clicked"<<endl);
	// Prende il nome della label, che per me rappresenta l'indice del vettore 
	// della mia mano di gioco.	
	const char *num_lab = gtk_label_get_text(GTK_LABEL(data));
	
	// Testo della label convertito ad intero.
	int indice=atoi(num_lab);

	gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(builder,num_lab)),
						false);	
	partita.player1.mano[indice].selez=true;
	
	setta_immagine_tavolo();
	D2(cout<<"settato le immagini sul tavolo con successo"<<endl);
	// passa il turno gestendo il punto del gioco in cui sono
	passa_turno();

	if (partita.id_fine == 19){
		gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(builder,"f")),"fine partita");
	}
	D1(cout<<"FINE DEBUG CARTA BUTTON CLICKED"<<endl);
}

/** Segnale che gestisce il mazzo premuto.
 *  Il mazzo viene premuto solo alla fine di una mano, ovvero quando la 
 *  variabile turno è = a secondo, cioè entrambi i giocatori hanno giocato.
 *  Permette di pescare una carta.
 */
extern "C" void mazzo_button_clicked(GtkButton *button, gpointer data){
	D1(cout<<"INIZIO DEBUG mazzo_button_clicked"<<endl);

	partita.id_fine++;
	// controlla fine partita
	gestore_fine_partita();
	D2(cout<<"controllo sulla fine della partita fatto con successo"<<endl);
	// Ricarica la mano solo alla fine di entrambi i turni, con le carte nuove.
	carica_mano();
	D2(cout<<"caricato la mani con successo"<<endl);
	// libera il campo di gioco
	pulisci_tavolo();
	D2(cout<<"pulito il tavolo con successo"<<endl);
	gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder,"mazzo"))
						,false);
	// recupera la label delle carte mancanti
	const char *c1=gtk_label_get_text(GTK_LABEL(gtk_builder_get_object(builder, 
						"indice")));
	char c2[3];
	c2[0]=c1[0];
	c2[1]=c1[1];
	c2[2]='\0';
	// aggiorna il numero delle carte mancanti
	int v;
	v = (c2[0]-'0')*10 + c2[1]-'0';
	v-=2;
	c2[0]=v/10+'0';
	c2[1]=v%10+'0';

	gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(builder, "indice")), c2);
	D2(cout<<"settato il testo della label correttamente"<<endl);
	
	if(gioca==computer){
		gioca_mano_pc();
		D2(cout<<"il computer ha giocato con successo"<<endl);	
		turno = secondo;
		}	
	
	/* Ogni volta che il turno cambia, risetta la sensibilità delle carte del giocatore 
	 * che deve giocare.
	 */ 
	setta_mano();	
	D2(cout<<"settato la mani con successo"<<endl);
	D1(cout<<"FINE DEBUG MAZZO BUTTON CLICKED"<<endl);
	
}

/** Main del programma. Avvia la partita richiamando la funzione 
 *  inizializza_partita, e in più setta solo il mazzo a non sensible e con 
 *  l'immagine della carta girata.
 */
int main(int argc, char *argv[]) {

	D1(cout<<"INIZIO DEBUG MAIN"<<endl);

	/* Call this function before using any other GTK+ 
	 * functions in your GUI applications. It will initialize 
	 * everything needed to operate the toolkit and parses 
	 * some standard command line options.

	 * Although you are expected to pass the argc, argv 
	 * parameters from main() to this function, it is possible 
	 * to pass NULL if argv is not available or commandline 	
	 * handling is not required.

	 * argc and argv are adjusted accordingly so your own 
	 * code will never see those standard arguments.
	 */
	gtk_init(&argc, &argv);

	//Creazione di un nuovo oggetto GtkBuilder
	builder = gtk_builder_new();

	//Caricamento dell'interfaccia nel nostro programma
	gtk_builder_add_from_file(builder,"BRISC.glade",NULL);

   //connessione di tutti i segnali
   gtk_builder_connect_signals(builder, NULL);

	//INIZIO:
	
	inizializza_partita();
 	D2(cout<<"inizielizzato la partita con successo"<<endl);
     	
	gtk_image_set_from_file(GTK_IMAGE(gtk_builder_get_object(builder,"mazz")),
						"./Carte/retro.jpg");
		
	gtk_image_set_from_file(GTK_IMAGE(gtk_builder_get_object(builder,"image1")),
						partita.mazzo[6].nome);

	// setta a non sensitive il mazzo
	gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder,"mazzo")),
						false);

	//Partenza del ciclo di gestione degli eventi
   gtk_main();
	
	return 0;
}
